<template>
  <div id="webgl-container" class="webgl-container">
    <canvas id="webgl" class="webgl"/>
  </div>

  <MoreInfo>
    <p>AmbientLight(环境光) - 提供基础照明</p>
    <p>DirectionalLight(方向光) - 模拟太阳光</p>
    <p>PointLight(点光源) - 从一点向四周发射光线</p>
    <p>SpotLight(聚光灯) - 锥形光线</p>
    <p>HemisphereLight(半球光) - 模拟天空和地面的反射光</p>
  </MoreInfo>
</template>

<script setup>
import {
  Mesh,
  SphereGeometry,
  MeshBasicMaterial,
  MeshLambertMaterial,
  MeshPhongMaterial,
  MeshStandardMaterial,
  MeshPhysicalMaterial,
  MeshToonMaterial,
  PlaneGeometry,
  AmbientLight,
  DirectionalLight,
  PointLight,
  SpotLight,
  HemisphereLight,
  DirectionalLightHelper,
  PointLightHelper,
  SpotLightHelper
} from 'three'

import MoreInfo from '@/components/MoreInfo.vue'
import { useThree } from '@/hooks/use-three-hook'

// 创建几何体和材质的辅助函数
const createObjects = (scene) => {
  const objects = []

  // 1. 基础网格材质 (MeshBasicMaterial) - 不受光照影响
  const basicMaterial = new MeshBasicMaterial({
    color: 0xff0000
  })
  const basicGeometry = new SphereGeometry(1, 32, 32)
  const basicSphere = new Mesh(basicGeometry, basicMaterial)
  basicSphere.position.set(-4, 3, 0)
  scene.add(basicSphere)
  objects.push(basicSphere)

  // 2. Lambert材质 (MeshLambertMaterial) - 漫反射材质
  const lambertMaterial = new MeshLambertMaterial({
    color: 0x00ff00
  })
  const lambertGeometry = new SphereGeometry(1, 32, 32)
  const lambertSphere = new Mesh(lambertGeometry, lambertMaterial)
  lambertSphere.position.set(0, 3, 0)
  scene.add(lambertSphere)
  objects.push(lambertSphere)

  // 3. Phong材质 (MeshPhongMaterial) - 镜面反射材质
  const phongMaterial = new MeshPhongMaterial({
    color: 0x0000ff,
    shininess: 100
  })
  const phongGeometry = new SphereGeometry(1, 32, 32)
  const phongSphere = new Mesh(phongGeometry, phongMaterial)
  phongSphere.position.set(4, 3, 0)
  scene.add(phongSphere)
  objects.push(phongSphere)

  // 4. Standard材质 (MeshStandardMaterial) - 基于物理的渲染材质
  const standardMaterial = new MeshStandardMaterial({
    color: 0xffff00,
    metalness: 0.8,
    roughness: 0.2
  })
  const standardGeometry = new SphereGeometry(1, 32, 32)
  const standardSphere = new Mesh(standardGeometry, standardMaterial)
  standardSphere.position.set(-4, 0, 0)
  scene.add(standardSphere)
  objects.push(standardSphere)

  // 5. 物理材质 (MeshPhysicalMaterial) - 扩展的Standard材质
  const physicalMaterial = new MeshPhysicalMaterial({
    color: 0xff00ff,
    metalness: 0.2,
    roughness: 0.1,
    clearcoat: 1.0,
    clearcoatRoughness: 0.1
  })
  const physicalGeometry = new SphereGeometry(1, 32, 32)
  const physicalSphere = new Mesh(physicalGeometry, physicalMaterial)
  physicalSphere.position.set(0, 0, 0)
  scene.add(physicalSphere)
  objects.push(physicalSphere)

  // 6. Toon材质 (MeshToonMaterial) - 卡通着色材质
  const toonMaterial = new MeshToonMaterial({
    color: 0x00ffff
  })
  const toonGeometry = new SphereGeometry(1, 32, 32)
  const toonSphere = new Mesh(toonGeometry, toonMaterial)
  toonSphere.position.set(4, 0, 0)
  scene.add(toonSphere)
  objects.push(toonSphere)

  // 创建地板
  const floorGeometry = new PlaneGeometry(20, 20)
  const floorMaterial = new MeshStandardMaterial({
    color: 0xffffff,
    metalness: 0.1,
    roughness: 0.8
  })
  const floor = new Mesh(floorGeometry, floorMaterial)
  floor.rotation.x = -Math.PI / 2
  floor.position.y = -1
  scene.add(floor)

  return objects
}

// 设置光源
const setupLights = (scene) => {
  // 环境光 - 提供基础照明
  const ambientLight = new AmbientLight(0xffffff, 0.3)
  scene.add(ambientLight)

  // 方向光 - 模拟太阳光
  const directionalLight = new DirectionalLight(0xffffff, 0.8)
  directionalLight.position.set(5, 5, 5)
  directionalLight.castShadow = true
  directionalLight.shadow.mapSize.width = 1024
  directionalLight.shadow.mapSize.height = 1024
  scene.add(directionalLight)

  // 点光源 - 从一点向四周发射光线
  const pointLight = new PointLight(0xff0000, 1, 100)
  pointLight.position.set(0, 3, 0)
  pointLight.castShadow = true
  scene.add(pointLight)

  // 聚光灯 - 锥形光线
  const spotLight = new SpotLight(0x00ff00, 1, 100, Math.PI / 4, 0.5)
  spotLight.position.set(-5, 5, 0)
  spotLight.castShadow = true
  scene.add(spotLight)

  // 半球光 - 模拟天空和地面的反射光
  const hemisphereLight = new HemisphereLight(0xffffbb, 0x080820, 0.5)
  scene.add(hemisphereLight)

  return {
    ambientLight,
    directionalLight,
    pointLight,
    spotLight,
    hemisphereLight
  }
}

// 添加光源助手来可视化光源位置
const addLightHelpers = (scene, lights) => {
  const directionalLightHelper = new DirectionalLightHelper(
    lights.directionalLight,
    1
  )
  scene.add(directionalLightHelper)

  const pointLightHelper = new PointLightHelper(lights.pointLight, 0.5)
  scene.add(pointLightHelper)

  const spotLightHelper = new SpotLightHelper(lights.spotLight)
  scene.add(spotLightHelper)

  return {
    directionalLightHelper,
    pointLightHelper,
    spotLightHelper
  }
}

const { scene, camera, addAnimationCallback } = useThree()
onMounted(() => {
  if (!scene.value) return

  // 创建物体
  createObjects(scene.value)

  // 设置光源
  const lights = setupLights(scene.value)

  // 添加光源助手
  const helpers = addLightHelpers(scene.value, lights)

  // 设置相机位置
  camera.value.position.set(0, 5, 10)
  camera.value.lookAt(0, 0, 0)

  // 动画回调 - 移动光源
  addAnimationCallback((delta, elapsedTime) => {
    // 移动点光源
    lights.pointLight.position.x = Math.sin(elapsedTime) * 3
    lights.pointLight.position.z = Math.cos(elapsedTime) * 3

    // 更新光源助手
    helpers.pointLightHelper.update()
    helpers.spotLightHelper.update()
  })
})
</script>
